//
//  ViewController.m
//  DCTest
//
//  Created by Joinwe on 16/6/7.
//  Copyright © 2016年 Joinwe. All rights reserved.
//

#import "ViewController.h"
#import "DCRequest.h"
#import "TwoTimesArray.h"
#import "ThreeTimesArray.h"
#import <objc/objc.h>
#import <objc/runtime.h>
#import <pthread.h>
#import "BLEInfo.h"
#import "DCViewController.h" 

#import <AFNetworking/AFNetworking.h>


#import <SocketRocket/SRWebSocket.h>


#import <ReactiveObjC/ReactiveObjC.h>
#import <AsyncDisplayKit/AsyncDisplayKit.h>


//#import <CoreImage/CoreImage.h>
#import <GPUImage/GPUImage.h>
#import "UIImage+ImageEffects.h"
#import "DCFilterEffect.h"
#import "FlowerView.h"
#import "FlowTransformView.h"
#import "GraphView.h"

#import "Tools.h"

#import "PersonTest.h"
#import "PersonViewModel.h"
#import "ArrayDataSource.h"


//本地安全验证
#import <LocalAuthentication/LocalAuthentication.h>

#define kDiviceSize [UIScreen mainScreen].bounds.size
#define kServiceUUID @"2F3E731C-8478-47C3-B636-E98BF36467B2"
#define kCharacteristicUUID @"02C53F8D-09DF-4FBF-80D9-AD23F30FCFF7"

//父类
@interface Person : NSObject

@property (nonatomic, copy) NSString *name;

@property (nonatomic, copy) NSString *sex;

@property (nonatomic, copy) NSString *age;

@property (nonatomic, copy) NSString *height;

- (void)eat;

@end

@implementation Person

- (void)eat{
    NSLog(@"这是Person的吃");
}

@end

//子类
@interface Man : Person

@end

@implementation Man

- (void)eat{
    NSLog(@"这是Man的吃");
}

@end

//控制器
@interface ViewController ()<CBCentralManagerDelegate,CBPeripheralDelegate,CBPeripheralManagerDelegate,UITableViewDelegate,UITableViewDataSource,SRWebSocketDelegate>{
    int a;
    CAEmitterLayer * _fireEmitter;//发射器对象
}

@property (nonatomic, retain) Person *person;

@property (nonatomic, retain) CBCentralManager *manger;

@property (nonatomic, retain) CBPeripheralManager *peripheralManger;

@property (nonatomic, retain) CBMutableService *peripheralService;

@property (nonatomic, retain) CBCharacteristic *peripheralCharacteristic;

@property (nonatomic, retain) NSMutableArray *array;

@property (nonatomic, retain) UITableView *tableView;

//锁
@property (nonatomic, strong) NSLock *lock;


@property (nonatomic, strong) SRWebSocket *webSocket;

@property (nonatomic, strong) PersonViewModel *model;


@end

static NSString *const KVO_CONTEXT_AGE_CHANGED = @"KVO_CONTEXT_AGE_CHANGED";

#define WEB_SOCKET @"http://127.0.0.1:8000"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self test27];
}

- (void)test27{
    NSString *dateString = @"2017,02,01,12,01,01";
    dateString = [dateString stringByReplacingOccurrencesOfString:@"," withString:@""];
    
    NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
    inputFormatter.dateFormat = @"yyyyMMddHHmmss";

    NSDate *date = [inputFormatter dateFromString:dateString];
    NSLog(@"日期为----%@",date);
    
    NSDateFormatter *outPutFormatter = [[NSDateFormatter alloc] init];
    outPutFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSString *outPutString = [outPutFormatter stringFromDate:date];
    NSLog(@"输出日期为----%@",outPutString);
    
}

- (void)test26{
    self.view.backgroundColor=[UIColor blackColor];
    //设置发射器
    _fireEmitter=[[CAEmitterLayer alloc]init];
    _fireEmitter.emitterPosition=CGPointMake(self.view.frame.size.width/2,self.view.frame.size.height-20);
    _fireEmitter.emitterSize=CGSizeMake(self.view.frame.size.width-100, 20);
    _fireEmitter.renderMode = kCAEmitterLayerAdditive;
    //发射单元
    //火焰
    CAEmitterCell * fire = [CAEmitterCell emitterCell];
    fire.birthRate=800;
    fire.lifetime=2.0;
    fire.lifetimeRange=1.5;
    fire.color=[[UIColor colorWithRed:0.8 green:0.4 blue:0.2 alpha:0.1]CGColor];
    fire.contents=(id)[[UIImage imageNamed:@"2.png"]CGImage];
    [fire setName:@"fire"];
    
    fire.velocity=160;
    fire.velocityRange=80;
    fire.emissionLongitude=M_PI+M_PI_2;
    fire.emissionRange=M_PI_2;
    
    
    
    fire.scaleSpeed=0.3;
    fire.spin=0.2;
    
    //烟雾
    CAEmitterCell * smoke = [CAEmitterCell emitterCell];
    smoke.birthRate=400;
    smoke.lifetime=3.0;
    smoke.lifetimeRange=1.5;
    smoke.color=[[UIColor colorWithRed:1 green:1 blue:1 alpha:0.05]CGColor];
    smoke.contents=(id)[[UIImage imageNamed:@"2.png"]CGImage];
    [fire setName:@"smoke"];
    
    smoke.velocity=250;
    smoke.velocityRange=100;
    smoke.emissionLongitude=M_PI+M_PI_2;
    smoke.emissionRange=M_PI_2;
    
    _fireEmitter.emitterCells=[NSArray arrayWithObjects:smoke,fire,nil];
    [self.view.layer addSublayer:_fireEmitter];
}

//RAC练习
- (void)test25{
    //第一种
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 64, kDEVICE_WIDTH - 20, 50)];
    button.backgroundColor = [UIColor greenColor];
    button.layer.cornerRadius = 5;
    [self.view addSubview:button];
    
    
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [subscriber sendNext:@"ws"];
        [subscriber sendCompleted];
        
        return [RACDisposable disposableWithBlock:^{
            NSLog(@"信号被销毁了");
        }];
    }];
    
    
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"接收到的数据----%@",x);
    }];

}

//ASDK练习
- (void)test24{
    ASButtonNode *button = [[ASButtonNode alloc] init];
    button.backgroundColor = [UIColor lightGrayColor];
    button.cornerRadius = 5;
    [button setTitle:@"测试" withFont:nil withColor:[UIColor greenColor] forState:ASControlStateNormal];
    button.contentVerticalAlignment = ASVerticalAlignmentTop;
    button.contentHorizontalAlignment = ASHorizontalAlignmentMiddle;
    
    [button measure:CGSizeMake(self.view.bounds.size.width, CGFLOAT_MAX)];
    button.frame = CGRectMake(10, 60, kDEVICE_WIDTH - 20, 50);
//    button.laysOutHorizontally = YES;
//    button.contentSpacing = 200.0f;
    
    [self.view addSubnode:button];
    
    
    
    
    ASTextNode *textNode = [[ASTextNode alloc] init];
    textNode.attributedString = [[NSAttributedString alloc] initWithString:@"世界你好！" attributes:@{NSForegroundColorAttributeName:[UIColor blackColor],NSFontAttributeName:[UIFont systemFontOfSize:17]}];
    textNode.frame = CGRectMake(20, 200, kDEVICE_WIDTH - 40, 30);
    [textNode addTarget:self action:@selector(textClick) forControlEvents:ASControlNodeEventTouchUpInside];
    [self.view addSubnode:textNode];
}


- (void)textClick{
    NSLog(@"Hello World!");
}


//更轻量的 dataSource
- (void)test23{
    
}


//测试MVVM
- (void)test22{
    self.model = [[PersonViewModel alloc] initWithPerson:[[PersonTest alloc] initWithName:@"张三" age:@"20" sex:@"男"]];
    
    UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 40, 200, 20)];
    nameLabel.text = self.model.nameText;
    [self.view addSubview:nameLabel];
    
    UILabel *ageLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 80, 200, 20)];
    ageLabel.text = self.model.ageText;
    [self.view addSubview:ageLabel];
    
    UILabel *sexLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 120, 200, 20)];
    sexLabel.text = self.model.sexText;
    [self.view addSubview:sexLabel];
}


//测试CocoaAsyncSocket
- (void)test21{

}

//测试WebScoket
- (void)test20{
    [self connectSocket];
}

- (void)connectSocket{
    if (_webSocket == nil) {
        _webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:WEB_SOCKET]]];
        _webSocket.delegate = self;
        [_webSocket open];
    }
}

#pragma mark - SRWebSocketDelegate 协商具体聊天逻辑
- (void)webSocketDidOpen:(SRWebSocket *)webSocket{
    NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
    [dictionary setValue:@"subscribe" forKey:@"cmd"];
    [dictionary setValue:@"test" forKey:@"ver"];
    [dictionary setValue:@"test" forKey:@"sid"];
    [dictionary setValue:@"1" forKey:@"channel"];
    [dictionary setValue:@"test" forKey:@"client_id"];
     NSLog(@"dictionary:%@",[Tools dictionaryToJson:dictionary]);
    
    [_webSocket send:[Tools dictionaryToJson:dictionary]];
}

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message{
    NSLog(@"---%@",message);
}




- (void)test19{
    NSLog(@"测试runloop");

//    AFHTTPSessionManager *httpManger = [AFHTTPSessionManager manager];
//    [httpManger GET:@"http://localhost/thinkphp/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
//        NSLog(@"成功----%@",responseObject);
//    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//        NSLog(@"失败----%@",error.localizedDescription);
//    }];
//    
//    
//    
//    [[DCRequest shareDCRequest] callWithWithBaseURL:@"http://localhost/" path:@"thinkphp/" menu:nil requestType:DCRequestTypeGet parameter:@{@"test":@"测试"} callBack:^(DCResponse * _Nullable response) {
//        NSLog(@"---%@",response.data);
//    }];
    
    
    
//    CFRunLoopRef run = CFRunLoopGetMain();
    
    
    [NSThread detachNewThreadSelector:@selector(newThreadProgress) toTarget:self withObject:nil];
    
}

- (void)newThreadProgress{
    @autoreleasepool {
        //获得当前thread的RunLoop
        NSRunLoop *myRunLoop = [NSRunLoop currentRunLoop];
        
        //设置Run Loop Observer的运行环境
        CFRunLoopObserverContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
        
        
        //创建Run loop observer对象
        //第一个参数用于分配observer对象的内存
        //第二个参数用以设置observer所要关注的事件，详见回调函数myRunLoopObserver中注释
        //第三个参数用于标识该observer是在第一次进入runloop时执行还是每次进入run loop处理时均执行
        //第四个参数用于设置该observer的优先级
        //第五个参数用于设置该observer的回调函数
        //第六个参数用于设置该observer的运行环境
        
        CFRunLoopObserverRef observer = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, &myRunLoopObserver, &context);
        
        if(observer){
            //将Cocoa的NSRunLoop类型转换成CoreFoundation的CFRunLoopRef类型
            CFRunLoopRef cfRunLoop = [myRunLoop getCFRunLoop];
            
            //将新建的observer加入到当前thread的runloop
            CFRunLoopAddObserver(cfRunLoop, observer, kCFRunLoopDefaultMode);
        }
        
        //
        [NSTimer scheduledTimerWithTimeInterval: 1 target: self selector:@selector(timerProcess) userInfo: nil repeats: YES];
        NSInteger loopCount = 2;
        do{
            //启动当前thread的loop直到所指定的时间到达，在loop运行时，runloop会处理所有来自与该run loop联系的inputsource的数据
            //对于本例与当前run loop联系的inputsource只有一个Timer类型的source。
            //该Timer每隔1秒发送触发事件给runloop，run loop检测到该事件时会调用相应的处理方法。
            
            //由于在run loop添加了observer且设置observer对所有的runloop行为都感兴趣。
            //当调用runUnitDate方法时，observer检测到runloop启动并进入循环，observer会调用其回调函数，第二个参数所传递的行为是kCFRunLoopEntry。
            //observer检测到runloop的其它行为并调用回调函数的操作与上面的描述相类似。
            [myRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.0]];
            //当run loop的运行时间到达时，会退出当前的runloop。observer同样会检测到runloop的退出行为并调用其回调函数，第二个参数所传递的行为是kCFRunLoopExit。
            loopCount--;
        }while (loopCount);
    
    }
}

void myRunLoopObserver(CFRunLoopObserverRef observer,CFRunLoopActivity activity,void *info){
    switch (activity) {
            //The entrance of the run loop, beforeentering the event processing loop.
            //This activity occurs once for each callto CFRunLoopRun and CFRunLoopRunInMode
        case kCFRunLoopEntry:
            NSLog(@"run loop entry");
            break;
            //Inside the event processing loop beforeany timers are processed
        case kCFRunLoopBeforeTimers:
            NSLog(@"run loop before timers");
            break;
            //Inside the event processing loop beforeany sources are processed
        case kCFRunLoopBeforeSources:
            NSLog(@"run loop before sources");
            break;
            //Inside the event processing loop beforethe run loop sleeps, waiting for a source or timer to fire.
            //This activity does not occur ifCFRunLoopRunInMode is called with a timeout of 0 seconds.
            //It also does not occur in a particulariteration of the event processing loop if a version 0 source fires
        case kCFRunLoopBeforeWaiting:
            NSLog(@"run loop before waiting");
            break;
            //Inside the event processing loop afterthe run loop wakes up, but before processing the event that woke it up.
            //This activity occurs only if the run loopdid in fact go to sleep during the current loop
        case kCFRunLoopAfterWaiting:
            NSLog(@"run loop after waiting");
            break;
            //The exit of the run loop, after exitingthe event processing loop.
            //This activity occurs once for each callto CFRunLoopRun and CFRunLoopRunInMode
        case kCFRunLoopExit:
            NSLog(@"run loop exit");
            break;
            /*
             A combination of all the precedingstages
             case kCFRunLoopAllActivities:
             break;
             */
        default:
            break;
    }
}

- (void)timerProcess{
    for (int i=0; i<5; i++) {
        NSLog(@"In timerProcess count = %d.", i);
        sleep(1);
    }
}

- (void)test18{
    /**
    对于图片压的功能，我们可以使用UIImageJPEGRepresentation或UIImagePNGRepresentation方法实现
    UIImageJPEGRepresentation函数需要两个参数:图片的引用和压缩系数而UIImagePNGRepresentation只需要图片引用作为参数，压缩系数不宜太低，通常是0.3~0.7，过小则可能会出现黑边等。
    如果对图片的清晰度要求不是极高,建议使用UIImageJPEGRepresentation，可以大幅度降低图片数据量，而且清晰度并没有相差多少,图片的质量并没有明显的降低。
     **/
        UIImage *image1 = [UIImage imageNamed:@"美女.jpg"];
        NSData *img1Data = UIImageJPEGRepresentation(image1, 0.5);
    
        NSLog(@"img1Data  %@",img1Data);
    
        UIImage *image2 = [UIImage imageNamed:@"2"];
        NSData *img2Data = UIImagePNGRepresentation(image2);
    
        NSLog(@"img2Data  %@",img2Data);
    
    
        UIImage *image = [UIImage imageWithData: img1Data];
    
    
}
//对图片进行缩放处理
- (UIImage *)compressImage:(UIImage *)sourceImage toTargetWidth:(CGFloat)targetWidth {
    CGSize imageSize = sourceImage.size;
    
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;
    
    CGFloat targetHeight = (targetWidth / width) * height;
    
    UIGraphicsBeginImageContext(CGSizeMake(targetWidth, targetHeight));
    [sourceImage drawInRect:CGRectMake(0, 0, targetWidth, targetHeight)];
    
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return newImage;
}


- (void)test17{
    //添加手机密码验证：
    //创建安全验证对象
    LAContext *con = [[LAContext alloc]init];
    NSError *error;
    //判断是否支持密码验证
    /**
     *LAPolicyDeviceOwnerAuthentication 手机密码的验证方式
     *LAPolicyDeviceOwnerAuthenticationWithBiometrics 指纹的验证方式
     */
    BOOL can = [con canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error];
    if (can) {
        [con evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:@"验证信息" reply:^(BOOL success, NSError * _Nullable error) {
            NSLog(@"%d,%@",success,error);
        }];
    }
    
    
    //进行指纹验证：
    LAContext *con1 = [[LAContext alloc]init];
    NSError *error1;
    BOOL can1 = [con1 canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error1];
    NSLog(@"%d",can1);
    if (can1) {
        [con1 evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"验证指纹" reply:^(BOOL success, NSError * _Nullable error) {
            NSLog(@"%d,%@",success,error1);
        }];
    }
    
    
}

- (void)test16{
//    UIKit是最高级的界面，是OC中唯一的界面。可以通过UI点缀来识别UIKit的元素，比如UIView和UIBezierPath，也扩展了NSString来利用方法(比如：drawInRect:withAttributes:)简化文本绘制
//    FlowerView *flower = [[FlowerView alloc] initWithFrame:self.view.bounds];

//    FlowTransformView *flower = [[FlowTransformView alloc] initWithFrame:self.view.bounds];
//    flower.backgroundColor = [UIColor blueColor];
//    [self.view addSubview:flower];
    
    
//    Core Graphics(也称为Quartz 2D) UIKit 下的主要绘图系统，频繁用于绘制自定义视图。 Core Graphics 跟 UIView 和 UIKit 其他部分高度集成。可以通过 CG 前缀来识别。
    GraphView *graph = [[GraphView alloc] initWithFrame:self.view.bounds];
    graph.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:graph];
    
//    Core Animation 提供了强大的2D 和 3D动画服务，它也与 UIView 高度集成。
    
    
    
    
//    Core Image 提供了非常快的图片过滤方式，比如切图、锐化、扭曲和其他你能想象的变形效果。
    //前面的滤镜里面介绍过
    
//    OpenGL ES //太底层了 不说了
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (void)test15{
    //    适应
    self.edgesForExtendedLayout = UIRectEdgeNone;
    self.view.backgroundColor = [UIColor redColor];
    
    UIButton *pushButton = [[UIButton alloc] initWithFrame:CGRectMake(20, 20, kDiviceSize.width - 40, 40)];
    pushButton.backgroundColor = [UIColor greenColor];
    [pushButton setTitle:@"PUSH" forState:UIControlStateNormal];
    [pushButton addTarget:self action:@selector(pushAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:pushButton];
}

- (void)pushAction{
    [self.navigationController pushViewController:[DCViewController new] animated:YES];
}

- (void)test14{
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(20, 64, 280, 50)];
    button.backgroundColor = [UIColor greenColor];
    [button addTarget:self action:@selector(alertShow) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (void)alertShow{
    UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
    }];
    
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
    }];
    
//    UIAlertController *alertC = [[UIAlertController alloc] init];
    UIAlertController *alertC  = [UIAlertController alertControllerWithTitle:@"警告" message:@"这是一个警告" preferredStyle:UIAlertControllerStyleAlert];
    [alertC addAction:sureAction];
    [alertC addAction:cancelAction];
    [self presentViewController:alertC animated:YES completion:nil];
}

- (void)test13{
    
    UIImage *loadImage=[UIImage imageNamed:@"美女.jpg"]; //获取图片
    CIImage *image = [[CIImage alloc] initWithImage:loadImage]; //将图片转换为CIImage
    
    
    
    CIFilter *filter = [CIFilter filterWithName:@"CIPhotoEffectMono"]; //根据滤镜名创建滤镜
    [filter setValue:image forKey:kCIInputImageKey]; //设置输入图片属性
    //    [filter setValue:@5.0f forKey:@"inputAngle"];
    //    [filter setValue:@5.0f forKey:@"inputRadius"];
    CIImage *result = [filter valueForKey:kCIOutputImageKey]; //获取输出图片内容
    //    CIImage *result = [filter outputImage]; //也可以这样写
    
    CIContext *context = [CIContext contextWithOptions:nil]; //获取绘制上下文
    CGImageRef outImage = [context createCGImage:result fromRect:[result extent]]; //将输出的内容绘制
    UIImage *blurImage = [UIImage imageWithCGImage:outImage]; //获取图片
    
    DCFilterEffect *DCFilter = [[DCFilterEffect alloc] initWithImage:loadImage filterName:@"CIPhotoEffectInstant"];
    
    
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20, kDiviceSize.width, kDiviceSize.height - 20)];
    imageView.image = DCFilter.result;
//    [self.view addSubview:imageView];
    
    
    GPUImageGaussianBlurFilter * blurFilter = [[GPUImageGaussianBlurFilter alloc] init];
    blurFilter.blurRadiusInPixels = 2.0;
    
    UIImageView *imageView1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20, kDiviceSize.width, kDiviceSize.height - 20)];
    imageView1.image = [blurFilter imageByFilteringImage:loadImage];;
    [self.view addSubview:imageView1];
    
    
    
    UIImageView *me = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20 + 2 * (kDiviceSize.height - 20) / 3, kDiviceSize.width, (kDiviceSize.height - 20) / 3)];
    [me setImage:[[UIImage imageNamed:@"美女.jpg"] applyBlurWithRadius:5 tintColor:[UIColor colorWithWhite:1 alpha:0.2] saturationDeltaFactor:1.8 maskImage:nil]];
    //    [self.view addSubview:me];
    
    
    
}


- (void)test12{
    self.peripheralManger = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
}

#pragma mark -------- CBPeripheralManager   Delegate
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{
    switch (peripheral.state) {
        case CBPeripheralManagerStatePoweredOn:
            [self setupService];
            break;
        default:
            NSLog(@"改变状态");
            break;
    }
}

- (void)setupService{
    //服务的UUID
    CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID];
    
    self.peripheralService = [[CBMutableService alloc] initWithType:serviceUUID primary:YES];
    
    //特征的UUID
    CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID];
    
    //这里初始化特征，给出可读的权限（可选的）
    self.peripheralCharacteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicUUID properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];
    //给服务设置特征
    [self.peripheralService setCharacteristics:@[self.peripheralCharacteristic]];
    
    //将服务添加到管理中
    [self.peripheralManger addService:self.peripheralService];
    
}

//添加服务之后
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error{
    //如果成功
    if (!error) {
        //开启广播
        [self.peripheralManger startAdvertising:@{CBAdvertisementDataLocalNameKey : @"LocalWeather", CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:kServiceUUID]]}];
    }
}

//这里是订阅中心委托代理，很少使用
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic{
    if ([characteristic isEqual:self.peripheralCharacteristic]){
        NSLog(@"这是订阅委托");
    }
}



- (void)test11{
    self.manger = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    self.array = [NSMutableArray array];
    
    self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, kDiviceSize.width, kDiviceSize.height - 64) style:UITableViewStylePlain];
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
    [self.view addSubview:self.tableView];
}

#pragma mark -------- CBCentralManager Delegate
//开启蓝牙之后
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
        case CBCentralManagerStatePoweredOn:
            //开始扫描
            [self.manger scanForPeripheralsWithServices:nil options:nil];
            NSLog(@"正在扫描");
            break;
            
        default:
            NSLog(@"状态改了");
            break;
    }
}

//扫描获取外围设备的信息
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{
    
    //这里也可以不在扫描外围设备
    //[self.manger stopScan];
    
    //如果数组中不包含这个对象，就添加
    if (![self.array containsObject:peripheral]) {
        peripheral.delegate = self;
        [self.array addObject:peripheral];
        [self.tableView reloadData];
    }
    NSLog(@"advertisementData === %@ ==== peripheral ==== %@ ===== RSSI ====== %@",advertisementData, peripheral ,RSSI);
    
}

//如果连接成功走这里
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    //发现外围设备的服务
    [peripheral discoverServices:nil];
}

//发现新特性
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    [peripheral.services enumerateObjectsUsingBlock:^(CBService * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        //可以在这里通过UUID来判断是不是我们的服务然后去发现新特性
        NSLog(@"该设备的服务有 ： %@", obj);
        CBService *service = obj;
        
        [peripheral discoverCharacteristics:nil forService:service];
    }];
}

//返回已经发现的新特性的委托方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    [service.characteristics enumerateObjectsUsingBlock:^(CBCharacteristic * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        //这里可以根据特性的UUID来做发出指令的判断
        CBCharacteristic *ch = obj;
        [peripheral setNotifyValue:YES forCharacteristic:ch];
    }];
}

//在委托中获取数值变化
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    NSLog(@"获得数值变化 %@", characteristic.value);
}

#pragma mark ------ TableViewDataSource && TableViewDelegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.array.count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 44;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellID = @"cellID";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellID];
    }
    
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    
    if (self.array.count != 0) {
        CBPeripheral *bleInfo = [self.array objectAtIndex:indexPath.row];
        
        cell.textLabel.text = [bleInfo.identifier UUIDString];
        //        cell.textLabel.text = bleInfo.name;
        //        NSLog(@"%@", bleInfo.discoveredPeripheral.identifier);
    }
    
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    if (self.array.count != 0) {
        CBPeripheral *bleInfo = [self.array objectAtIndex:indexPath.row];
        
        //连接外围设备
        [self.manger connectPeripheral:bleInfo options:nil];
        
    }
    
}



- (void)test10{
    
    //第一种方式：可以直接跟在任务后面编写需要完成的操作，如这里在下载图片后，紧跟着下载第二张图片。但是这种写法有的时候把两个不相关的操作写到了一个代码块中，代码的可阅读性不强。
    //创建对象，封装操作
    NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"第一种方式-operation-下载图片-%@",[NSThread currentThread]);
        //.....下载图片后继续进行的操作
        NSLog(@"第一种方式--接着下载第二张图片--");
    }];
    //创建队列
    NSOperationQueue *queue=[[NSOperationQueue alloc]init];
    //把任务添加到队列中（自动执行，自动开线程）
    [queue addOperation:operation];
    
    
    //第二种方式：
    //创建对象，封装操作
    NSBlockOperation *operation1=[NSBlockOperation blockOperationWithBlock:^{
        for (int i=0; i<10; i++) {
            NSLog(@"第二种方式-operation-下载图片-%@",[NSThread currentThread]);
        }
    }];
    //监听操作的执行完毕
    operation1.completionBlock=^{
        //.....下载图片后继续进行的操作
        NSLog(@"第二种方式--接着下载第二张图片--");
    };
    //创建队列
    NSOperationQueue *queue1=[[NSOperationQueue alloc]init];
    //把任务添加到队列中（自动执行，自动开线程）
    [queue1 addOperation:operation1];
    
    
}

- (void)test9{
    //创建NSInvocationOperation对象，封装操作
    NSInvocationOperation *operation1=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(dependencyTest1) object:nil];
    NSInvocationOperation *operation2=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(dependencyTest2) object:nil];
    //创建对象，封装操作
    NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^{
        for (int i=0; i<5; i++) {
            NSLog(@"NSBlockOperation3--1----%@",[NSThread currentThread]);
        }
    }];
    [operation3 addExecutionBlock:^{
        for (int i=0; i<5; i++) {
            NSLog(@"NSBlockOperation3--2----%@",[NSThread currentThread]);
        }
    }];
    
    //设置操作依赖
    //先执行operation2，再执行operation1，最后执行operation3
    [operation3 addDependency:operation1];
    [operation1 addDependency:operation2];
    
    //不能是相互依赖
    //    [operation3 addDependency:operation1];
    //    [operation1 addDependency:operation3];
    
    //创建NSOperationQueue
    NSOperationQueue * queue=[[NSOperationQueue alloc]init];
    //把操作添加到队列中
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
}


-(void)dependencyTest1{
    for (int i=0; i<5; i++) {
        NSLog(@"NSInvocationOperation--test1--%@",[NSThread currentThread]);
    }
}
-(void)dependencyTest2{
    for (int i=0; i<5; i++) {
        NSLog(@"NSInvocationOperation--test2--%@",[NSThread currentThread]);
    }
}


- (void)test8{
    
    //创建NSInvocationOperation对象，封装操作
    NSInvocationOperation *operation1=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationTest1) object:nil];
    NSInvocationOperation *operation2=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationTest2) object:nil];
    //创建对象，封装操作
    NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"NSBlockOperation3--1----%@",[NSThread currentThread]);
    }];
    [operation3 addExecutionBlock:^{
        NSLog(@"NSBlockOperation3--2----%@",[NSThread currentThread]);
    }];
    
    
    //创建NSOperationQueue
    NSOperationQueue * queue=[[NSOperationQueue alloc]init];
    //把操作添加到队列中
    //第一种方式
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
    //第二种方式
    [queue addOperationWithBlock:^{
        NSLog(@"NSBlockOperation3--4----%@",[NSThread currentThread]);
    }];
    
}

- (void)operationTest1{
    NSLog(@"NSInvocationOperation--test1--%@",[NSThread currentThread]);
}

- (void)operationTest2{
    NSLog(@"NSInvocationOperation--test2--%@",[NSThread currentThread]);
}

- (void)test7{
    //创建NSBlockOperation操作对象
    NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"NSBlockOperation------%@",[NSThread currentThread]);
    }];
    
    //添加操作
    [operation addExecutionBlock:^{
        NSLog(@"NSBlockOperation1------%@",[NSThread currentThread]);
    }];
    
    [operation addExecutionBlock:^{
        NSLog(@"NSBlockOperation2------%@",[NSThread currentThread]);
    }];
    //开启执行操作
    [operation start];
}


- (void)test6{
    //创建操作对象，封装要执行的任务
    //NSInvocationOperation   封装操作
    NSInvocationOperation *operation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationTest) object:nil];
    //执行操作
    [operation start];
}

- (void)operationTest{
    NSLog(@"--test--%@--",[NSThread currentThread]);
}


- (void)test5{
    a = 5;
    //开启多个线程，模拟售票员售票
    [NSThread detachNewThreadSelector:@selector(buyTickets1) toTarget:self withObject:nil];
    [NSThread detachNewThreadSelector:@selector(buyTickets2) toTarget:self withObject:nil];
    
    // 要用同一把锁
    //    _lock = [[NSLock alloc] init];
}

// 线程同步

// 甲买5张票
- (void)buyTickets1{
    // 锁是一个标志
    //        [_lock lock];
    @synchronized (self){
        NSLog(@"甲 准备买5张票");
        if (a >= 5){
            NSLog(@"票至少有5张,可以给甲办理买票");
            a = a - 5;
            NSLog(@"甲成功购买5张票,还剩%d张",a);
        }else{
            NSLog(@"票不够5张,不能买");
        }
    }
    //        [_lock unlock];
}

// 乙 买1 张票
- (void)buyTickets2{
    //    [_lock lock];
    @synchronized (self){
        // 线程同步块
        NSLog(@"乙 准备买1张票");
        if (a >= 1){
            NSLog(@"票至少有1张,可以给乙办理买票");
            a = a - 1;
            NSLog(@"乙成功购买1张票,还剩%d张",a);
        }else{
            NSLog(@"票不够1张,不能买");
        }
    }
    //    [_lock unlock];
}


- (void)test4{
    UITextView *text = [[UITextView alloc] initWithFrame:CGRectMake(20, 130, 280, 80)];
    text.layer.borderWidth = .5;
    text.layer.borderColor = [UIColor blueColor].CGColor;
    text.layer.cornerRadius = 4;
    [self.view addSubview:text];
    
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(20, 64, 280, 50)];
    button.backgroundColor = [UIColor greenColor];
    [button addTarget:self action:@selector(btnClick3) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

-(void)btnClick3{
    //1.获取当前线程
    NSThread *current=[NSThread currentThread];
    //主线程
    NSLog(@"btnClick----%@",current);
    //获取主线程的另外一种方式
    NSThread *main=[NSThread mainThread];
    NSLog(@"主线程-------%@",main);
    
    
    //2.执行一些耗时操作
    
    
    NSThread  *thread1=[[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"线程A"];
    //为线程设置一个名称
    thread1.name=@"线程A";
    //开启线程
    [thread1 start];
    
    
    
    NSThread  *thread2=[[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"线程B"];
    //为线程设置一个名称
    thread2.name=@"线程B";
    //开启线程
    [thread2 start];
    
    
    //创建完线程直接(自动)启动
    [NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"创建完线程直接(自动)启动"];
    
    
    //在后台线程中执行===在子线程中执行
    [self performSelectorInBackground:@selector(run:) withObject:@"隐式创建"];
}


- (void)run:(NSString *)string{
    //获取当前线程
    NSThread *current=[NSThread currentThread];
    //打印输出
    for (int i=0; i<10; i++) {
        NSLog(@"run---%@---%@",current,string);
    }
}



- (void)test3{
    UITextView *text = [[UITextView alloc] initWithFrame:CGRectMake(20, 130, 280, 80)];
    text.layer.borderWidth = .5;
    text.layer.borderColor = [UIColor blueColor].CGColor;
    text.layer.cornerRadius = 4;
    [self.view addSubview:text];
    
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(20, 64, 280, 50)];
    button.backgroundColor = [UIColor greenColor];
    [button addTarget:self action:@selector(btnClick2) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

//古老的方式创建
- (void)btnClick2{
    //1.获取当前线程
    NSThread *current=[NSThread currentThread];
    //主线程
    NSLog(@"btnClick----%@",current);
    //2.使用for循环执行一些耗时操作
    pthread_t thread;
    pthread_create(&thread, NULL, run, NULL);
}

void *run(void *data){
    //获取当前线程，是新创建出来的线程
    NSThread *current=[NSThread currentThread];
    for (int i=0; i<10000; i++) {
        NSLog(@"btnClick---%d---%@",i,current);
    }
    return NULL;
}


- (void)test2{
    UITextView *text = [[UITextView alloc] initWithFrame:CGRectMake(20, 130, 280, 80)];
    text.layer.borderWidth = .5;
    text.layer.borderColor = [UIColor blueColor].CGColor;
    text.layer.cornerRadius = 4;
    [self.view addSubview:text];
    
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(20, 64, 280, 50)];
    button.backgroundColor = [UIColor greenColor];
    [button addTarget:self action:@selector(btnClick1) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}


- (void)btnClick1{
    NSThread *current = [NSThread currentThread];
    for (int i = 0; i < 10000; i ++) {
        NSLog(@"btnClick---%d---%@",i,current);
    }
}


- (void)test1{
    self.person = [[Person alloc] init];
    [self.person setValue:@"徐卫星" forKey:@"name"];
    [self.person setValue:@"90" forKey:@"age"];
    [self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:(__bridge void * _Nullable)(KVO_CONTEXT_AGE_CHANGED)];
    NSLog(@"%@",[self valueForKeyPath:@"person.name"]);
    Person *man = [Man new];
    [man eat];
    
    
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(20, 60, 100, 40)];
    button.backgroundColor = [UIColor greenColor];
    [button addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    
    
//    [[DCRequest shareDCRequest] callWithWithBaseURL:@"http://192.168.1.131:8080/resource/" path:@"project/all" menu:nil requestType:DCRequestTypeGet parameter:@{@"pageIndex":@"1", @"pageSize":@"10", @"platformType": @"1"} callBack:^(DCResponse * _Nullable response) {
//        NSLog(@"%@",response.data[@"errorcCode"]);
//    }];
    
    [[DCRequest shareDCRequest] callWithWithBaseURL:@"http://127.0.0.1:80/webtest/" path:@"index.php" menu:nil requestType:DCRequestTypePost parameter:@{@"username":@"admin", @"password":@"123456"} callBack:^(DCResponse * _Nullable response) {
                NSLog(@"%@",response.data);
        }];
    
    NSArray *array = [NSArray arrayWithObjects:@"10.11",@"20.22", nil];
    
    NSArray *resultArray = [array valueForKeyPath:@"doubleValue.intValue"];
    
    NSLog(@"%@",resultArray);
    
    NSLog(@"%@",[array valueForKeyPath:@"@sum.doubleValue"]);
    
    
    
    TwoTimesArray *twoTimesArray = [[TwoTimesArray alloc] init];
    twoTimesArray.count = 3;
    NSArray *twoTimes = [twoTimesArray valueForKey:@"numbers"];
    //twoTimes为KVC代理数组
    NSLog(@"======%@", twoTimes);
    
    
    
    ThreeTimesArray *threeTimesArray = [[ThreeTimesArray alloc] init];
    threeTimesArray.numbers = [NSMutableArray array];
    NSMutableArray *threeTimes = [threeTimesArray mutableArrayValueForKey:@"numbers"];
    //threeTimes为KVC代理可变数组，非指向elfinsArr.elfins
    [threeTimes insertObject:@"这是个数" atIndex:0];
    NSLog(@"first log n %@", threeTimesArray.numbers);
    [threeTimes removeObjectAtIndex:0];
    NSLog(@"second log n %@", threeTimesArray.numbers);
}



- (void)btnClick{
    [self.person setValue:@"100" forKey:@"age"];
}


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    if(context == (__bridge void * _Nullable)(KVO_CONTEXT_AGE_CHANGED)) {
        NSString *name = [object valueForKey:@"name"];
        NSString *address = [object valueForKey:@"age"];
        NSLog(@"%@ has a 升级了: %@", name, address);
    }
}




/**
 简单的一个排序算法

 @param a a
 @param b b
 */
void swap(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

//顺序，太慢
void bubble_sort(int a[], int n){
    int i, j, y = 1;
    for (j = 0; j < n - 1; j++){
        for (i = 0; i < n - 1 - j; i++){
            if(a[i] > a[i + 1]){
                swap(&a[i], &a[i + 1]);
            }
            y ++;
        }
    }
    printf("循环次数为 %d", y);
}

//逆序，太慢
void bubble_sortB(int a[], int n){
    int i, j, y=1;
    for (j = 0; j < n - 1; j++){
        for (i = 0; i < n - 1 - j; i++){
            if(a[i] < a[i + 1]){
                swap(&a[i], &a[i + 1]);
            }
            y ++;
        }
    }
    printf("循环次数为 %d", y);
}


- (void)viewDidLoadTest {
    int a[19];
    //    int j = 0;
    //    for (int i = 19; i >= 0; i--) {
    //        a[j++] = i;
    //    }
    
    for (int i = 0; i < 19; i++) {
        a[i] = i;
    }
    bubble_sortB(a, 19);
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    
}

@end
